package communication.common.business.mail;

import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPMessage;
import com.sun.mail.imap.IMAPStore;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

/**
 * @author mac
 */
public class MailUtils {

    /**
     * 进行远程连接的邮件标题
     */
    public static final String ACTION_REMOTE_CONNECT="ACTION_REMOTE_CONNECT";


    /**
     * 发送邮件
     * @throws Exception
     */
    public static boolean sendMail( EmailUserConfig  emailUserConfig,SimpleMail simpleMail)
            throws Exception {

        if (simpleMail != null && emailUserConfig != null){
            Properties props = System.getProperties();
            props.put("mail.smtp.host", emailUserConfig.getSmtpHost());
            props.put("mail.smtp.auth", "true");
            MailAuthenticator auth = new MailAuthenticator();
            MailAuthenticator.USERNAME = emailUserConfig.getMailAccount();
            MailAuthenticator.PASSWORD = emailUserConfig.getPwd();
            Session session = Session.getInstance(props, auth);
            session.setDebug(true);
            try {
                MimeMessage message = new MimeMessage(session);
                message.setFrom(new InternetAddress(emailUserConfig.getMailAccount()));
                if (!simpleMail.getReceiver().trim().equals("")) {
                    message.addRecipient(Message.RecipientType.TO,
                            new InternetAddress(simpleMail.getReceiver().trim()));
                }
                message.setSubject(simpleMail.getSubject());
                MimeBodyPart mbp1 = new MimeBodyPart(); // 正文
                mbp1.setContent(simpleMail.getContent(), "text/html;charset=utf-8");
                Multipart mp = new MimeMultipart(); // 整个邮件：正文+附件
                mp.addBodyPart(mbp1);
                // mp.addBodyPart(mbp2);
                message.setContent(mp);
                message.setSentDate(new Date());
                message.saveChanges();
                Transport trans = session.getTransport("smtp");
                Transport.send(message);
            } catch (Exception e){
                e.printStackTrace();
                return false;
            }
            return true;
        }else{
            return false;
        }
    }


    /**
     * 接收邮件
     */
    public static void receiveMail(EmailUserConfig config, MonitorMailConfig monitorMailConfig) throws MessagingException, IOException {
        //1、连接邮件服务器的参数配置
        Properties props = new Properties();
        //设置传输协议
        props.setProperty("mail.store.protocol", "imap");
        //设置收件人的POP3服务器  ， pop3协议无法判断邮件状态是否为已读，只有IMAP协议可以
        props.setProperty("mail.imap.host", config.getImapHost());
        //2、创建定义整个应用程序所需的环境信息的 Session 对象
        Session session = Session.getInstance(props);
        //设置调试信息在控制台打印出来
        //session.setDebug(true);

        IMAPStore store = (IMAPStore)session.getStore("imap");
        //连接收件人POP3服务器
        store.connect(config.getImapHost(), config.getMailAccount(), config.getPwd());
        //获得用户的邮件账户，注意通过pop3协议获取某个邮件夹的名称只能为inbox
        IMAPFolder folder = (IMAPFolder)store.getFolder("inbox");
        //设置对邮件账户的访问权限
        folder.open(Folder.READ_WRITE);
        // 根据过滤配置对邮件进行过滤
        List<Message>  filterMsgs = filterByMonitorConfig(folder.getMessages(),monitorMailConfig);

        // 处理邮件
        handleMails(filterMsgs,folder);

        //关闭邮件夹对象
        folder.close(false);

        //关闭连接对象
        store.close();
    }

    /**
     * 处理过滤后的邮件
     * @param filterMsgs
     * @param folder
     */
    private static void handleMails(List<Message> filterMsgs, IMAPFolder folder) throws MessagingException {
        if(CollectionUtils.isEmpty(filterMsgs)){
            return;
        }

        Message[] modify=new Message[filterMsgs.size()];

        // 设置邮件为已读
        folder.setFlags( filterMsgs.toArray(modify), new Flags(Flags.Flag.SEEN),true);

        // todo:根据主题进行处理, 后期可以考虑将处理的动作抽离为接口
        filterMsgs.forEach(MailUtils::handleMailsBySubject);
    }

    /**
     * 根据主题处理邮件
     */
    private static void handleMailsBySubject(Message msg){
        try{
            //获得邮件主题
            String subject = msg.getSubject();
            //获得邮件发件人
            InternetAddress from = (InternetAddress)msg.getFrom()[0];
            //Message表示一个邮件，msg.getContent()返回一个Multipart对象。一个Multipart对象包含一个或多个BodyPart对象，来组成邮件的正文部分（包括附件）。
            MimeMultipart mimeMultipart = (MimeMultipart)msg.getContent();
            String content = mimeMultipart.getBodyPart(0).getContent().toString();
            System.out.println("邮件主题:"+subject);
            System.out.println("邮件内容:"+content);
            System.out.println("邮件发件人:"+from.getPersonal()+",邮箱地址:"+from.getAddress());

            SimpleMail simpleMail = SimpleMail.builder()
                    .subject(msg.getSubject())
                    .content(content)
                    .receiver(from.getAddress())
                    .build();


            switch (simpleMail.getSubject()){
                // 进行远程连接 todo:
                case ACTION_REMOTE_CONNECT:
                    actionRemoteConnect(simpleMail);
                    break;
                default:
                    throw new Exception("暂不支持的ACTION:"+msg.getSubject());
            }
        }catch (Exception e){
            // 暂时只打印异常
            System.out.println(e);
        }
    }

    /**
     * 进行远程连接
     *  连接流程:
     *      1. server端接收到邮件里传来的ip地址
     *
     *
     * @param msg
     */
    private static void actionRemoteConnect(SimpleMail msg) throws MessagingException, IOException {

        // todo:



    }

    /**
     * 根据过滤配置对邮件进行过滤
     * @param messages
     * @param monitorMailConfig
     * @return
     */
    private static List<Message> filterByMonitorConfig(Message[] messages, MonitorMailConfig monitorMailConfig) throws MessagingException {
        if(messages==null || messages.length==0 ){
            return null;
        }

        if(monitorMailConfig == null){
            return Arrays.asList(messages);
        }

        List<Message> msgs = new ArrayList<>();

        //  -------- 过滤 -------

        for (Message msg: messages ) {
            // 过滤掉已读邮件
            IMAPMessage imapMessage=(IMAPMessage) msg;
            if(imapMessage.getFlags().contains(Flags.Flag.SEEN)){
                continue;
            }

            // 根据发送人过滤
            if (!StringUtils.isEmpty(monitorMailConfig.getFrom())) {
                InternetAddress internetAddress = (InternetAddress) msg.getFrom()[0];
                if (!monitorMailConfig.getFrom().equals(internetAddress.getAddress())) {
                    continue;
                }
                // 根据邮件主题过滤
                if (!StringUtils.isEmpty(monitorMailConfig.getSubject())) {
                    if (!monitorMailConfig.getSubject().equals(msg.getSubject())) {
                        continue;
                    }
                }
                msgs.add(msg);
            }
        }

        return  msgs;
    }


}

class MailAuthenticator extends Authenticator{
    public static String USERNAME = "";
    public static String PASSWORD = "";

    public MailAuthenticator() {
    }

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(USERNAME, PASSWORD);
    }

}

